home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / DEMO_VGA / GIFUTIL.LZH / GIFSTAT.C < prev    next >
C/C++ Source or Header  |  1988-01-21  |  13KB  |  515 lines

  1. /* GIFSCAN - scans through a GIF file and reports all parameters */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6.  
  7. void    colormap(int out, FILE *dev, int times);
  8. unsigned int getbytes(FILE *dev);
  9. void    extninfo(FILE *dev);
  10. void    chkunexp(int *unexpected, int determiner);
  11. void    imageinf(FILE *dev, int bits_to_use, int color_style);
  12.  
  13. #define MAX 255
  14.  
  15.  
  16. /************************************************************************/
  17. /* MAIN - the main routine reads the GIF file for the global GIF        */
  18. /*        information which it displays to the user's screen.  This     */
  19. /*        routine also determines which subroutine to call and which    */
  20. /*        information to process.                                       */
  21.  
  22.  
  23. #define DEC "-d"
  24. #define HEX "-h"
  25. #define PCT "-p"
  26. #define DECIMAL 1
  27. #define PERCENT 2
  28. #define HEXIDEC 3
  29.  
  30.  
  31. main(int argc, char *argv[])
  32. {
  33.     char filename[15];
  34.     char version[7];
  35.     char style[5];
  36.  
  37.     int byte1;
  38.     int byte2;
  39.     int byte3;
  40.     int color_res;
  41.     int unexpected;
  42.     int image_cnt;
  43.     int bits_per_pix;
  44.     int bits_to_use;
  45.     int colors;
  46.     int i;
  47.     int globl;
  48.     int end_gif_fnd;
  49.     int color_style;
  50.     int switch_present;
  51.  
  52.     unsigned int width;
  53.     unsigned int height;
  54.  
  55.     FILE *in;
  56.  
  57.     /* Start of Processing */
  58.  
  59.     /* If just one argument then display the message */
  60.  
  61.     if (argc == 1) {
  62.     printf("\nUSAGE:    gifscan  color_opt  filename\n");
  63.     printf("\ncolor_opt   specifies how color lookup table");
  64.     printf("\n            definitions are displayed");
  65.     printf("\n  -h  :     output as hexidecimal (0 - FF) (default)");
  66.     printf("\n  -d  :     output as decimal (0 - 255)");
  67.     printf("\n  -p  :     output as percentage (0 - 100)\n");
  68.     return;
  69.     }
  70.  
  71.     color_style = 0;
  72.     switch_present = 0;
  73.  
  74.     if ((strnicmp(argv[1], "-", 1) == 0)) {
  75.     switch_present = 1;
  76.     strcpy(style, argv[1]);
  77.     }
  78.     else
  79.     switch_present = 0;
  80.  
  81.     do {
  82.     if ((strnicmp(style, DEC, 2) == 0))
  83.         color_style = DECIMAL;
  84.     else if ((strnicmp(style, PCT, 2) == 0))
  85.         color_style = PERCENT;
  86.     else
  87.         color_style = HEXIDEC;
  88. #if 0
  89.     else if ((strnicmp(style, HEX, 2) == 0))
  90.         color_style = HEXIDEC;
  91.     else {
  92.         printf("\nEnter Colormap style (-h, -p, -d) : ");
  93.         gets (style);
  94.     }
  95. #endif
  96.     }
  97.     while (color_style == 0)
  98.     ;
  99.  
  100.     
  101.     /* Check for GIF filename */
  102.  
  103.     do {
  104.     if ((argc == 1) || ((argc == 2) && (switch_present == 1))) {
  105.         printf("\nEnter GIF filename:  ");
  106.         gets (filename);
  107.     }
  108.     else
  109.         if (argc == 3)
  110.         strcpy(filename, argv[2]);
  111.         else
  112.         strcpy(filename, argv[1]);
  113.  
  114.     in = fopen (filename, "rb");
  115.     argc = 1;
  116.     }
  117.     while (in == NULL)
  118.     ;
  119.  
  120.     image_cnt = 0;
  121.     end_gif_fnd = 0;
  122.     unexpected = 0;
  123.  
  124.     /* get version from file */
  125.  
  126.     if ((version[0] = getc(in)) == 0x47) {
  127.     for (i = 1; (i < 6); i++)
  128.         version[i] = getc(in);
  129.     version[6] = '\0';
  130.     printf("\nVersion: %s", version);
  131.     }
  132.     else {
  133.     printf("\n? -- NOT a GIF file\n");
  134.     exit(1);
  135.     }
  136.  
  137.  
  138.     /* determine screen width */
  139.  
  140.     width = getbytes(in);
  141.  
  142.     /* determine screen height */
  143.  
  144.     height = getbytes(in);
  145.     printf("\nScreen Width:     %5d\tScreen Height:    %5d", width, height);
  146.  
  147.     /* check for a Global Map */
  148.  
  149.     byte1 = getc(in);
  150.     byte2 = byte1 & 0x80;
  151.     if (byte2 == 0x80) {
  152.     printf("\nGlobal Color Map: Yes");
  153.     globl = 1;
  154.     }
  155.     else {
  156.     printf("\nGlobal Color Map: No");
  157.     globl = 0;
  158.     }
  159.  
  160.     /* Check for the 0 bit */
  161.  
  162.     byte2 = byte1 & 0x08;
  163.     if (byte2 != 0)
  164.     printf("\n? -- Reserved zero bit is not zero.\n");
  165.  
  166.     /* determine the color resolution */
  167.  
  168.     byte2 = byte1 & 0x70;
  169.     color_res = byte2 >> 4;
  170.  
  171.  
  172.     /* get the background index */
  173.  
  174.     byte3 = getc(in);
  175.     printf("\nColor res:  %5d\tBackground index:  %5d", ++color_res, byte3);
  176.  
  177.     /* determine the bits per pixel */
  178.  
  179.     bits_per_pix = byte1 & 0x07;
  180.     bits_per_pix++;
  181.     bits_to_use = bits_per_pix;
  182.  
  183.     /* determine # of colors in global map */
  184.  
  185.     colors = 1 << bits_per_pix;
  186.     printf("\nBits per pixel: %5d\t# colors:  %5d\n", bits_per_pix, colors);
  187.  
  188.  
  189.     /* check for the 0 byte */
  190.  
  191.     byte1 = getc(in);
  192.     if (byte1 != 0)
  193.     printf("\n? -- Reserved byte after Background index is not zero.\n");
  194.  
  195.     if (globl == 1)
  196.     colormap (color_style, in, colors);
  197.  
  198.     /* check for the zero byte count, a new image, or */
  199.     /* the end marker for the gif file */
  200.  
  201.     while ((byte1 = getc(in)) != EOF) {
  202.     if (byte1 == ',') {
  203.         image_cnt++;
  204.         if (unexpected != 0)
  205.         chkunexp(&unexpected, image_cnt);
  206.         printf("\nImage # %2d", image_cnt);
  207.         imageinf(in, bits_to_use, color_style);
  208.     }
  209.     else if (byte1 == '!')
  210.         extninfo (in);
  211.  
  212.     else if (byte1 == ';') {
  213.         if (unexpected != 0)
  214.         chkunexp(&unexpected, -1);
  215.         end_gif_fnd = 1;
  216.     }
  217.     else
  218.         unexpected++;
  219.  
  220.     }
  221.  
  222.     /* EOF has been reached - check last bytes read */
  223.  
  224.     if (end_gif_fnd == 0)
  225.     printf("\n? -- GIF file terminator ';' was not found.\n");
  226.     else
  227.     if (unexpected != 0)
  228.         chkunexp(&unexpected, -2);
  229. }
  230.  
  231.  
  232.  
  233. /************************************************************************/
  234. /* COLORMAP - reads color information in from the GIF file and displays */
  235. /*            it in a user selected method.  This display may be in :   */
  236. /*            hexidecimal (default), percentage, or decimal.  User      */
  237. /*            selects output method by placing a switch (-d, -p, -h)    */
  238. /*            between the program name and GIF filename at request time.*/
  239. void
  240. colormap(int out, FILE *dev, int times)
  241. {
  242.     unsigned int red;
  243.     unsigned int green;
  244.     unsigned int blue;
  245.  
  246.     int print_cnt;
  247.     int i;
  248.  
  249.     /* Start of procedure */
  250.  
  251.     if (out == DECIMAL)
  252.     printf("\nColor definitions in decimal   (index #, R, G, B)\n");
  253.  
  254.     if (out == PERCENT)
  255.     printf("\nColor definitions by percentage   (index #, R, G, B)\n");
  256.  
  257.     if (out == HEXIDEC)
  258.     printf("\nColor definitions in hexidecimal    (index #, R, G, B)\n");
  259.  
  260.     /* read and print the color definitions */
  261.  
  262.     print_cnt = 0;
  263.  
  264.     for (i = 0; (i < times); i++) {
  265.     red = getc(dev);
  266.     green = getc(dev);
  267.     blue = getc(dev);
  268.  
  269.     switch (out) {
  270.     case DECIMAL :
  271.         printf("%3d - %3d %3d %3d  ", i, red, green, blue);
  272.         break;
  273.     case PERCENT :
  274.         red = (red * 100) / MAX;
  275.         green = (green * 100) / MAX;
  276.         blue = (blue * 100) / MAX;
  277.         printf("%3d - %3d %3d %3d  ", i, red, green, blue);
  278.         break;
  279.     case HEXIDEC :
  280.         printf("%3d - %2x %2x %2x   ", i, red, green, blue);
  281.         break;
  282.     }
  283.     print_cnt++;
  284.     if (print_cnt == 4) {
  285.         printf("\n");
  286.         print_cnt = 0;
  287.     }
  288.     }
  289.     if ((times % 4) != 0)
  290.     printf("\n");
  291. }
  292.  
  293. /************************************************************************/
  294.  
  295. /* GETBYTES - routine to retrieve two bytes of information from the GIF */
  296. /*            file and then shift them into correct byte order.  The    */
  297. /*            information is stored in Least Significant Byte order.    */
  298.  
  299. unsigned int getbytes(FILE *dev)
  300. {
  301.     int byte1;
  302.     int byte2;
  303.     int result;
  304.  
  305.     /* read bytes and shift over */
  306.  
  307.     byte1 = getc(dev);
  308.     byte2 = getc(dev);
  309.  
  310.     result = (byte2 << 8) | byte1;
  311.  
  312.     return result;
  313.  
  314. }
  315.  
  316.  
  317. /***********************************************************************/
  318. /* IMAGEINF - routine to read the GIF image information and display it */
  319. /*            to the user's screen in an orderly fasion.  If there are */
  320. /*            multiple images then IMAGEINF will be called to display  */
  321. /*            multiple screens.                                        */
  322.  
  323. void
  324. imageinf(FILE *dev, int bits_to_use, int color_style)
  325. {
  326.     int byte1;
  327.     int byte2;
  328.     int image_left;
  329.     int image_top;
  330.     int data_byte_cnt;
  331.     int bits_per_pix;
  332.     int colors;
  333.     int i;
  334.     int local;
  335.  
  336.     unsigned int width;
  337.     unsigned int height;
  338.  
  339.     unsigned long bytetot;
  340.     unsigned long possbytes;
  341.  
  342.     /* determine the image left value */
  343.  
  344.     image_left = getbytes(dev);
  345.  
  346.     /* determine the image top value */
  347.  
  348.     image_top = getbytes(dev);
  349.     printf("\nImage Left: %5d\t\tImage Top: %5d", image_left, image_top);
  350.  
  351.     /* determine the image width */
  352.  
  353.     width = getbytes(dev);
  354.  
  355.     /* determine the image height */
  356.  
  357.     height = getbytes(dev);
  358.     printf("\nImage Width:    %5d\t\tImage Height:  %5d", width, height);
  359.  
  360.     /* check for interlaced image */
  361.  
  362.     byte1 = getc(dev);
  363.     byte2 = byte1 & 0x40;
  364.     if (byte2 == 0x40)
  365.     printf("\nInterlaced: Yes");
  366.     else
  367.     printf("\nInterlaced: No");
  368.  
  369.     /* check for a local map */
  370.  
  371.     byte2 = byte1 & 0x80;
  372.     if (byte2 == 0x80) {
  373.     local = 1;
  374.     printf("\nLocal Color Map: Yes");
  375.     }
  376.     else {
  377.     local = 0;
  378.     printf("\nLocal Color Map: No");
  379.     }
  380.  
  381.     /* check for the 3 zero bits */
  382.  
  383.     byte2 = byte1 & 0x38;
  384.     if (byte2 != 0)
  385.     printf("\n? -- Reserved zero bits in image not zeros.\n");
  386.  
  387.     /* determine the # of color bits in local map */
  388.  
  389.     bits_per_pix = byte1 & 0x07;
  390.     bits_per_pix++;
  391.     colors = 1 << bits_per_pix;
  392.  
  393.     if (local == 1) {
  394.     bits_to_use = bits_per_pix;
  395.     printf("\nBits per pixel: %5d\t\t# colors :     %5d", bits_per_pix,
  396.                                                        colors);
  397.     colormap (color_style, dev, colors);
  398.     }
  399.  
  400.     /* retrieve the code size */
  401.  
  402.     byte1 = getc(dev);
  403.     if ((byte1 < 2) || (byte1 > 8)) {
  404.     printf("\n? -- Code size %d at start of image");
  405.     printf("\n     is out of range (2-8).\n");
  406.     }
  407.     else
  408.     printf("\nLZW min code size (bits):  %3d", byte1);
  409.  
  410.     /* tally up the total bytes and read past each data block */
  411.  
  412.     bytetot = 0;
  413.     possbytes = 0;
  414.  
  415.     while ((data_byte_cnt = getc(dev)) > 0) {
  416.     bytetot = bytetot + data_byte_cnt;
  417.     for (i = 0; (i < data_byte_cnt); i++) {
  418.         byte2 = getc(dev);
  419.         if (byte2 == EOF) {
  420.         printf("\n? -- EOF reached inside image data block.\n");
  421.         exit (2);
  422.         }
  423.     }
  424.     }
  425.     possbytes = (unsigned long) width * height;
  426.     i = 8 / bits_to_use;
  427.     possbytes = possbytes / i;
  428.     printf("\nTotal bytes:  %ld out of possible  %ld\n", bytetot, possbytes);
  429.  
  430.     if (data_byte_cnt == EOF) {
  431.     printf("\n? -- EOF reached before zero byte count");
  432.     printf("\n     of image was read.\n");
  433.     exit (3);
  434.     }
  435. }
  436.  
  437.  
  438.  
  439. /************************************************************************/
  440. /* EXTNINFO - routine to read the GIF file for extension data and       */
  441. /*            display it to the screen in an orderly fasion.  This      */
  442. /*            extension information may be located before, between, or  */
  443. /*            after any of the image data.                              */
  444.  
  445. void
  446. extninfo(FILE *dev)
  447. {
  448.     int byte1;
  449.     int byte2;
  450.     int i;
  451.     int data_byte_cnt;
  452.  
  453.     unsigned long bytetot;
  454.  
  455.     /* retrieve the function code */
  456.  
  457.     byte1 = getc(dev);
  458.     printf("\nGIF extension seen, code :  %d", byte1);
  459.  
  460.     /* tally up the total bytes and read past each data block */
  461.  
  462.     bytetot = 0;
  463.  
  464.     while ((data_byte_cnt = getc(dev)) > 0) {
  465.     bytetot = bytetot + data_byte_cnt;
  466.     for (i = 0; (i < data_byte_cnt); i++) {
  467.         byte2 = getc(dev);
  468.         if (byte2 == EOF) {
  469.         printf("\n? -- EOF reached inside extension data block.\n");
  470.         exit (2);
  471.         }
  472.     }
  473.     }
  474.  
  475.     printf("\nTotal number of bytes in extension:  %ld\n", bytetot);
  476.  
  477.     if (data_byte_cnt == EOF) {
  478.     printf("\n? -- EOF was reached before zero byte count");
  479.     printf("\n     of extension was read.\n");
  480.     exit (3);
  481.     }
  482. }
  483.  
  484.  
  485. /************************************************************************/
  486. /* CHKUNEXP - routine to check for any unexpected nonzero data found    */
  487. /*            within the GIF file.  This routine will help determine    */
  488. /*            where the unexpected data may reside in the file.         */
  489.  
  490. void
  491. chkunexp (int *unexpected, int determiner)
  492. {
  493.     /* Determine place in the GIF file */
  494.  
  495.     if (determiner > 0) {
  496.     printf("\n? -- %d bytes of unexpected data found before",*unexpected);
  497.     printf("\n     image %d.\n", determiner);
  498.     }
  499.     else if (determiner == -1) {
  500.     printf("\n? -- %d bytes of unexpected data found before",
  501.                                               *unexpected);
  502.     printf("\n     GIF file terminator.\n");
  503.     }
  504.     else {
  505.     printf("\n? -- %d bytes of unexpected data found after",
  506.                                               *unexpected);
  507.     printf("\n     GIF file terminator.\n");
  508.     }
  509.  
  510.     /* Zero out unexpected variable for next group that may be encountered */
  511.  
  512.     *unexpected = 0;
  513. }
  514.  
  515.